const { query } = require('./db');

// 操作类型枚举
const ACTION_TYPES = {
  // 工单生命周期
  CREATED: 'created',
  UPDATED: 'updated',
  DELETED: 'deleted',
  CANCELLED: 'cancelled',
  
  // 状态变更
  STATUS_CHANGED: 'status_changed',
  ASSIGNED: 'assigned',
  UNASSIGNED: 'unassigned',
  REOPENED: 'reopened',
  RESOLVED: 'resolved',
  CLOSED: 'closed',
  
  // 验证流程
  VERIFICATION_REQUESTED: 'verification_requested',
  VERIFICATION_APPROVED: 'verification_approved',
  VERIFICATION_REJECTED: 'verification_rejected',
  
  // 评论和备注
  COMMENT_ADDED: 'comment_added',
  COMMENT_UPDATED: 'comment_updated',
  COMMENT_DELETED: 'comment_deleted',
  INTERNAL_NOTE_ADDED: 'internal_note_added',
  INTERNAL_NOTE_UPDATED: 'internal_note_updated',
  INTERNAL_NOTE_DELETED: 'internal_note_deleted',
  
  // 附件管理
  ATTACHMENT_ADDED: 'attachment_added',
  ATTACHMENT_REMOVED: 'attachment_removed',
  
  // 属性变更
  PRIORITY_CHANGED: 'priority_changed',
  CATEGORY_CHANGED: 'category_changed',
  DUE_DATE_CHANGED: 'due_date_changed',
  TAGS_UPDATED: 'tags_updated',
  
  // 权限变更
  PERMISSION_GRANTED: 'permission_granted',
  PERMISSION_REVOKED: 'permission_revoked'
};

// 日志级别
const LOG_LEVELS = {
  INFO: 'info',
  WARNING: 'warning',
  ERROR: 'error',
  CRITICAL: 'critical'
};

/**
 * 记录工单操作日志
 * @param {Object} logData - 日志数据
 * @param {number} logData.ticketId - 工单ID
 * @param {number} logData.userId - 操作用户ID
 * @param {string} logData.actionType - 操作类型
 * @param {string} logData.description - 操作描述
 * @param {Object} [logData.fieldChanges] - 字段变更详情
 * @param {Object} [logData.oldValues] - 变更前的值
 * @param {Object} [logData.newValues] - 变更后的值
 * @param {string} [logData.ipAddress] - 操作IP地址
 * @param {string} [logData.userAgent] - 用户代理信息
 * @param {string} [logData.level] - 日志级别
 */
async function logTicketAction(logData) {
  try {
    const {
      ticketId,
      userId,
      actionType,
      description,
      fieldChanges = null,
      oldValues = null,
      newValues = null,
      ipAddress = null,
      userAgent = null,
      level = LOG_LEVELS.INFO
    } = logData;

    // 验证必需字段
    if (!ticketId || !userId || !actionType || !description) {
      throw new Error('缺少必需的日志字段');
    }

    // 验证操作类型
    if (!Object.values(ACTION_TYPES).includes(actionType)) {
      throw new Error('无效的操作类型');
    }

    // 构建JSON数据
    const fieldChangesJson = fieldChanges ? JSON.stringify(fieldChanges) : null;
    const oldValuesJson = oldValues ? JSON.stringify(oldValues) : null;
    const newValuesJson = newValues ? JSON.stringify(newValues) : null;

    await query(
      `INSERT INTO ticket_logs 
       (ticket_id, user_id, action_type, action_description, field_changes, old_values, new_values, ip_address, user_agent) 
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
      [ticketId, userId, actionType, description, fieldChangesJson, oldValuesJson, newValuesJson, ipAddress, userAgent]
    );

    console.log(`[${level.toUpperCase()}] 工单 ${ticketId} 操作日志记录成功: ${actionType} - ${description}`);
  } catch (error) {
    console.error('记录工单操作日志失败:', error);
    // 记录日志失败不应该影响主要业务流程，所以这里只记录错误但不抛出异常
  }
}

/**
 * 快捷方法：记录状态变更日志
 */
async function logStatusChange(ticketId, userId, fromStatus, toStatus, ipAddress, userAgent) {
  await logTicketAction({
    ticketId,
    userId,
    actionType: ACTION_TYPES.STATUS_CHANGED,
    description: `工单状态从 "${fromStatus}" 变更为 "${toStatus}"`,
    fieldChanges: { status: true },
    oldValues: { status: fromStatus },
    newValues: { status: toStatus },
    ipAddress,
    userAgent
  });
}

/**
 * 快捷方法：记录分配变更日志
 */
async function logAssignmentChange(ticketId, userId, oldStaffId, newStaffId, oldStaffName, newStaffName, ipAddress, userAgent) {
  const actionType = newStaffId ? ACTION_TYPES.ASSIGNED : ACTION_TYPES.UNASSIGNED;
  const description = newStaffId 
    ? `工单分配给 ${newStaffName}`
    : `取消工单分配 (原分配人: ${oldStaffName})`;

  await logTicketAction({
    ticketId,
    userId,
    actionType,
    description,
    fieldChanges: { support_staff_id: true },
    oldValues: { support_staff_id: oldStaffId, support_staff_name: oldStaffName },
    newValues: { support_staff_id: newStaffId, support_staff_name: newStaffName },
    ipAddress,
    userAgent
  });
}

/**
 * 快捷方法：记录优先级变更日志
 */
async function logPriorityChange(ticketId, userId, fromPriority, toPriority, ipAddress, userAgent) {
  await logTicketAction({
    ticketId,
    userId,
    actionType: ACTION_TYPES.PRIORITY_CHANGED,
    description: `优先级从 "${fromPriority}" 变更为 "${toPriority}"`,
    fieldChanges: { priority: true },
    oldValues: { priority: fromPriority },
    newValues: { priority: toPriority },
    ipAddress,
    userAgent
  });
}

/**
 * 快捷方法：记录验证操作日志
 */
async function logVerificationAction(ticketId, userId, action, comment, ipAddress, userAgent) {
  const actionType = action === 'approve' ? ACTION_TYPES.VERIFICATION_APPROVED : ACTION_TYPES.VERIFICATION_REJECTED;
  const description = action === 'approve' 
    ? `用户验证通过${comment ? '：' + comment : ''}` 
    : `用户驳回验证${comment ? '：' + comment : ''}`;

  await logTicketAction({
    ticketId,
    userId,
    actionType,
    description,
    fieldChanges: { verification_status: true },
    oldValues: { verification_status: 'pending' },
    newValues: { verification_status: action === 'approve' ? 'approved' : 'rejected' },
    ipAddress,
    userAgent,
    level: LOG_LEVELS.INFO
  });
}

/**
 * 快捷方法：记录内部备注操作日志
 */
async function logInternalNoteAction(ticketId, userId, action, noteContent, ipAddress, userAgent) {
  const actionMap = {
    'added': ACTION_TYPES.INTERNAL_NOTE_ADDED,
    'updated': ACTION_TYPES.INTERNAL_NOTE_UPDATED,
    'deleted': ACTION_TYPES.INTERNAL_NOTE_DELETED
  };

  const actionType = actionMap[action];
  if (!actionType) {
    throw new Error('无效的内部备注操作类型');
  }

  const description = {
    'added': `添加了内部备注: ${noteContent.substring(0, 50)}${noteContent.length > 50 ? '...' : ''}`,
    'updated': `更新了内部备注: ${noteContent.substring(0, 50)}${noteContent.length > 50 ? '...' : ''}`,
    'deleted': `删除了内部备注: ${noteContent.substring(0, 50)}${noteContent.length > 50 ? '...' : ''}`
  }[action];

  await logTicketAction({
    ticketId,
    userId,
    actionType,
    description,
    ipAddress,
    userAgent
  });
}

/**
 * 获取工单操作日志
 * @param {number} ticketId - 工单ID
 * @param {number} [limit=50] - 限制返回数量
 * @param {number} [offset=0] - 偏移量
 */
async function getTicketLogs(ticketId, limit = 50, offset = 0) {
  try {
    return await query(`
      SELECT 
        tl.*,
        u.name as user_name,
        u.department as user_department,
        u.role as user_role
      FROM ticket_logs tl
      LEFT JOIN users u ON tl.user_id = u.id
      WHERE tl.ticket_id = ?
      ORDER BY tl.created_at DESC
      LIMIT ? OFFSET ?
    `, [ticketId, limit, offset]);
  } catch (error) {
    console.error('获取工单日志失败:', error);
    return [];
  }
}

/**
 * 批量记录字段变更日志
 * @param {number} ticketId - 工单ID
 * @param {number} userId - 操作用户ID
 * @param {Object} changes - 变更的字段对象 {fieldName: {old: oldValue, new: newValue}}
 * @param {string} ipAddress - IP地址
 * @param {string} userAgent - 用户代理
 */
async function logFieldChanges(ticketId, userId, changes, ipAddress, userAgent) {
  const fieldChanges = {};
  const oldValues = {};
  const newValues = {};
  const descriptions = [];

  Object.keys(changes).forEach(field => {
    const change = changes[field];
    fieldChanges[field] = true;
    oldValues[field] = change.old;
    newValues[field] = change.new;

    // 生成描述文本
    switch (field) {
      case 'title':
        descriptions.push(`标题从 "${change.old}" 变更为 "${change.new}"`);
        break;
      case 'description':
        descriptions.push(`描述内容已更新`);
        break;
      case 'category':
        descriptions.push(`类别从 "${change.old}" 变更为 "${change.new}"`);
        break;
      case 'due_date':
        descriptions.push(`预期完成时间从 "${change.old}" 变更为 "${change.new}"`);
        break;
      default:
        descriptions.push(`${field} 从 "${change.old}" 变更为 "${change.new}"`);
    }
  });

  await logTicketAction({
    ticketId,
    userId,
    actionType: ACTION_TYPES.UPDATED,
    description: descriptions.join('；'),
    fieldChanges,
    oldValues,
    newValues,
    ipAddress,
    userAgent
  });
}

module.exports = {
  ACTION_TYPES,
  LOG_LEVELS,
  logTicketAction,
  logStatusChange,
  logAssignmentChange,
  logPriorityChange,
  logVerificationAction,
  logInternalNoteAction,
  getTicketLogs,
  logFieldChanges
};